/*
 * Copyright 2017 hv0912
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.vimhe.ezimp2.handler;

import com.vimhe.ezimp2.Constants;
import com.vimhe.ezimp2.config.bean.ColumnConfig;
import com.vimhe.ezimp2.config.bean.FileConfig;
import com.vimhe.ezimp2.config.bean.FormatterConfig;
import com.vimhe.ezimp2.config.bean.RowConfig;
import com.vimhe.ezimp2.config.bean.SheetConfig;
import com.vimhe.ezimp2.config.bean.ValidatorConfig;
import com.vimhe.ezimp2.config.exception.ConfigException;
import com.vimhe.ezimp2.handler.bean.CellData;
import com.vimhe.ezimp2.handler.bean.FileData;
import com.vimhe.ezimp2.handler.bean.RowData;
import com.vimhe.ezimp2.handler.bean.SheetData;
import com.vimhe.ezimp2.handler.formatter.support.DateFormatter;
import com.vimhe.ezimp2.handler.formatter.support.NumberFormatter;
import com.vimhe.ezimp2.handler.validator.ErrorMessage;
import com.vimhe.ezimp2.handler.validator.support.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 默认数据读取器实现
 *
 * @author Vimhe
 */
public class DataHandler implements Reader, ErrorMessageResolver, Writer {

    /**
     * 数据验证器链
     */
    private final Map<String, Validator> validatorMap = new HashMap<>(32);

    /**
     * 错误消息列表
     */
    private final List<ErrorMessage> errorMessages = new ArrayList<>(128);

    /**
     * 数据转换器
     */
    private final Map<String, Formatter> formatterMap = new HashMap<>(32);

    protected DataHandler() {
        validatorMap.put(Constants.VALIDATOR_NAME_NULLABLE, new NullableValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_STRING_LENGTH, new StringLengthValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_STRING_MIN_LENGTH, new StringMinLengthValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_STRING_MAX_LENGTH, new StringMaxLengthValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_STRING_START_WITH, new StringStartWithValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_STRING_END_WITH, new StringEndWithValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_STRING_CONTAINS, new StringContainsValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_STRING_EQUALS, new StringEqualsValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_STRING_EQUALS_IGNORE_CASE, new StringEqualsIgnoreCaseValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_STRING_SEPARATOR, new StringSeparatorValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_NUMBER_EQUALS, new NumberEqualsValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_NUMBER_MIN, new NumberMinValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_NUMBER_MAX, new NumberMaxValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_DATETIME_START, new DatetimeStartValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_DATETIME_END, new DatetimeEndValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_DATETIME_BEFORE, new DatetimeBeforeValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_DATETIME_AFTER, new DatetimeAfterValidator());
        validatorMap.put(Constants.VALIDATOR_NAME_STRING_PATTERN, new StringPatternValidator());

        formatterMap.put(Constants.FORMATTER_NAME_NUMBER, new NumberFormatter());
        formatterMap.put(Constants.FORMATTER_NAME_DATE, new DateFormatter());
    }

    @Override
    public final void read(final CellData cellData, final ColumnConfig columnConfig) {
        // 遍历验证器配置以找到对应的验证器
        // 用找到的验证器验证当前单元格的数据
        for (ValidatorConfig validatorConfig : columnConfig.getValidatorConfigMap().values()) {
            Validator validator = validatorMap.get(validatorConfig.getName());
            if (validator == null) {
                throw new ConfigException("没有找到名为【" + validatorConfig.getName() + "】的验证器，请确认是否已注册");
            }

            ErrorMessage errorMessage = validator.validate(cellData, columnConfig);

            // 当任何一个验证器验证失败时，收集错误消息并停止对当前单元格的验证
            if (errorMessage != null) {
                this.errorMessages.add(errorMessage);
                this.onCellError(errorMessage);
            }
        }

        // 进行转换操作
        String formattedValue = "";
        for (FormatterConfig formatterConfig : columnConfig.getFormatterConfigMap().values()) {
            Formatter formatter = formatterMap.get(formatterConfig.getName());
            if (formatter == null) {
                throw new ConfigException("没有找到名为【" + formatterConfig.getName() + "】的格式转换器，请确认是否已注册");
            }

            try {
                formattedValue = formatter.format(formatterConfig.getValue(), formatterConfig.getValue());
            } catch (Exception e) {
                ErrorMessage errorMessage = new ErrorMessage(cellData).setErrorMessage(e.getMessage());
                this.errorMessages.add(errorMessage);
                this.onCellError(errorMessage);
            }
        }

        // 用最新的数据覆盖之前的数据
        cellData.setValue(formattedValue);

        this.write(cellData, columnConfig);
    }

    @Override
    public final void read(final RowData rowData, final RowConfig rowConfig) {
        this.onRowError(this.errorMessages);
        this.write(rowData, rowConfig);
    }

    @Override
    public final void read(final SheetData sheetData, final SheetConfig sheetConfig) {
        this.onSheetError(this.errorMessages);
        this.write(sheetData, sheetConfig);
    }

    @Override
    public final void read(final FileData fileData, final FileConfig fileConfig) {
        this.onFileError(this.errorMessages);
        this.write(fileData, fileConfig);
    }

    @Override
    public void onCellError(final ErrorMessage errorMessage) {

    }

    @Override
    public void onRowError(final List<ErrorMessage> errorMessages) {

    }

    @Override
    public void onSheetError(final List<ErrorMessage> errorMessages) {

    }

    @Override
    public void onFileError(final List<ErrorMessage> errorMessages) {

    }

    @Override
    public void write(final CellData cellData, final ColumnConfig columnConfig) {

    }

    @Override
    public void write(final RowData rowData, final RowConfig rowConfig) {

    }

    @Override
    public void write(final SheetData sheetData, final SheetConfig sheetConfig) {

    }

    @Override
    public void write(final FileData fileData, final FileConfig fileConfig) {

    }

    public final void addValidator(final Validator validator) {
        if (this.validatorMap.containsKey(validator.name())) {
            throw new ConfigException("已注册名为【" + validator.name() + "】的验证器，不能重新注册");
        }

        this.validatorMap.put(validator.name(), validator);
    }

    public final void addFormatter(final Formatter<?> formatter) {
        if (this.formatterMap.containsKey(formatter.name())) {
            throw new ConfigException("已注册名为【" + formatter.name() + "】的格式转换器，不能重新注册");
        }

        this.formatterMap.put(formatter.name(), formatter);
    }

}
